<template>
  <el-table
    ref="tableRef"
    class="ba-data-table w100"
    header-cell-class-name="table-header-cell"
    :default-expand-all="baTable.table.expandAll"
    :data="baTable.table.data"
    :row-key="baTable.table.pk"
    :border="true"
    v-loading="baTable.table.loading"
    stripe
    @select-all="onSelectAll"
    @select="onSelect"
    @selection-change="onSelectionChange"
    @sort-change="onSortChange"
    @row-dblclick="onDbClick"
    :show-summary="baTable.table.extend.summary"
    :summary-method="getSummaries"
    :span-method="objectSpanMethod"
    v-bind="$attrs"
    :row-style="pointer"
    :max-height="baTable.table.extend.maxHeight"
  >
    <template v-for="(item, key) in baTable.table.column" :key="key">
      <Column v-if="item.show !== false" :attr="item">
        <template v-if="item.render" #default="scope">
          <FieldRender
            :field="item"
            :key="
              item.render == 'switch' || 'switchAccess'
                ? 'column-' +
                  scope.column.property +
                  '-' +
                  key +
                  '-' +
                  scope.row[scope.column.property]
                : 0
            "
            :row="scope.row"
            :property="scope.column.property"
          />
        </template>
      </Column>
    </template>
  </el-table>
  <!-- 页脚 -->
  <div v-if="props.pagination" class="table-pagination">
    <el-pagination
      :currentPage="baTable.table.filter!.pageNum"
      :page-size="baTable.table.filter!.pageSize"
      :page-sizes="[10, 20, 50, 100]"
      background
      :layout="
        config.layout.shrink
          ? 'prev, next, jumper'
          : 'sizes,total, ->, prev, pager, next, jumper'
      "
      :total="baTable.table.total"
      @size-change="onTableSizeChange"
      @current-change="onTableCurrentChange"
    >
    </el-pagination>
  </div>
</template>
<script lang="ts" setup>
import _ from "lodash";
import { ref, nextTick, inject, provide, onBeforeUnmount } from "vue";
import { useRoute } from "vue-router";
import type baTableClass from "@/utils/baTable";
import { useConfig } from "@/store/config";
import type { ElTable } from "element-plus";
import Column from "@/components/table/column/index.vue";
import FieldRender from "./fieldRender/index.vue";
import useCurrentInstance from "@/utils/useCurrentInstance";
import type { TableColumn, TableRow, OptButton } from "@/utils/baTable"; //表格列行类型
import { useNavTabs } from "@/store/navTabs";
import type { TableColumnCtx } from "element-plus";
import { useElectricData } from "@/store/backend/DataM/RealTime";

const route = useRoute();
const config = useConfig();
const navTabs = useNavTabs();
const realTime = useElectricData();
const { proxy } = useCurrentInstance();
const tableRef = ref<InstanceType<typeof ElTable>>(); //el-table的实例
interface Props extends Partial<InstanceType<typeof ElTable>> {
  pagination?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
  pagination: true,
});

const isPointer = ref(false);

const baTable = inject("baTable") as baTableClass;

const emits = defineEmits<{
  (e: "action", event: string, data: any): void;
}>();

/*
 * 是否是全选操作
 * 只检查第一个元素是否被选择
 * 全选时：selectIds为所有元素的id
 * 取消全选时：selectIds为所有子元素的id
 */
const isSelectAll = (selectIds: string[]) => {
  let data = baTable.table.data as TableRow[];
  for (const key in data) {
    return selectIds.includes(data[key][baTable.table.pk!].toString());
  }
  return false;
};

/*
 * 选择子项-递归
 */
const selectChildren = (children: TableRow[], type: boolean) => {
  children.map((j: TableRow) => {
    toggleSelection(j, type);
    if (j.children) {
      selectChildren(j.children, type);
    }
  });
};

/*
 * 执行选择操作
 */
const toggleSelection = (row: TableRow, type: boolean) => {
  if (row) {
    nextTick(() => {
      tableRef.value?.toggleRowSelection(row, type);
    });
  }
};

/*
 * 全选和取消全选
 * 实现子级同时选择和取消选中
 */
const onSelectAll = (selection: TableRow[]) => {
  if (
    isSelectAll(
      selection.map((row: TableRow) => row[baTable.table.pk!].toString())
    )
  ) {
    selection.map((row: TableRow) => {
      if (row.children) {
        selectChildren(row.children, true);
      }
    });
  } else {
    tableRef.value?.clearSelection();
  }
};

/*
 * 合并行
 * row: 获取此行的全部数据，即你需要传入且展示的数据
 * column：获取列的结构及其数据、注意此时列的数据不是指我们传入的数据、而是饿了么自己定义的列结构。
 * rowIndex：行号，这个行号表示当前是第几行
 * columnIndex：列号，表示当前是第几列
 */

interface SpanMethodProps {
  row: TableRow;
  column: any;
  rowIndex: number;
  columnIndex: number;
}
const objectSpanMethod = ({
  row,
  column,
  rowIndex,
  columnIndex,
}: SpanMethodProps) => {
  if (baTable.table.extend.column) {
    let arr = _.cloneDeep(baTable.table.extend.columnFiled),
      len = arr.length;
    if (baTable.table.extend.columnMasteFiled) {
      for (let i = 0; i < len; i++) {
        //!按最高优先级字段合并
        let mergeIndex = _.findIndex(baTable.table.column, {
          prop: baTable.table.extend.columnFiled[i],
        });
        if (columnIndex === mergeIndex) {
          // 获取当前单元格的值
          const currentValue = row[baTable.table.extend.columnMasteFiled];
          // 获取上一行相同列的值
          const preRow = baTable.table.data![rowIndex - 1];
          const preValue = preRow
            ? preRow[baTable.table.extend.columnMasteFiled]
            : null;
          // 如果当前值和上一行的值相同，则将当前单元格隐藏
          if (currentValue === preValue) {
            return { rowspan: 0, colspan: 0 };
          } else {
            // 否则计算当前单元格应该跨越多少行
            let rowspan = 1;
            for (let i = rowIndex + 1; i < baTable.table.data!.length; i++) {
              const nextRow = baTable.table.data![i];
              const nextValue = nextRow[baTable.table.extend.columnMasteFiled];
              if (nextValue === currentValue) {
                rowspan++;
              } else {
                break;
              }
            }
            return { rowspan, colspan: 1 };
          }
        }
      }
    } else {
      for (let i = 0; i < len; i++) {
        let mergeIndex = _.findIndex(baTable.table.column, {
          prop: baTable.table.extend.columnFiled[i],
        });
        if (columnIndex === mergeIndex) {
          // 获取当前单元格的值
          const currentValue = row[column.property];
          // 获取上一行相同列的值
          const preRow = baTable.table.data![rowIndex - 1];
          const preValue = preRow ? preRow[column.property] : null;

          // 如果当前值和上一行的值相同，则将当前单元格隐藏
          if (currentValue === preValue) {
            return { rowspan: 0, colspan: 0 };
          } else {
            // 否则计算当前单元格应该跨越多少行
            let rowspan = 1;
            for (let i = rowIndex + 1; i < baTable.table.data!.length; i++) {
              const nextRow = baTable.table.data![i];
              const nextValue = nextRow[column.property];
              if (nextValue === currentValue) {
                rowspan++;
              } else {
                break;
              }
            }
            return { rowspan, colspan: 1 };
          }
        }
      }
    }

    // if (columnIndex === 1) {
    // if (rowIndex % 2 === 0) {
    //   return {
    //     rowspan: 2,
    //     colspan: 1,
    //   };
    // } else {
    //   return {
    //     rowspan: 0,
    //     colspan: 0,
    //   };
    // }
    // }
  }
};

/*
 * 合计方法 韩总项目的
 */

const getSummaries = (param: any) => {
  const { columns, data } = param;
  const sums: string[] = [];
  if (baTable.table.extend.summary) {
    //判断是哪个表格需要合计 合计的方式
    return rewriteBoardSalseOutPlan(
      baTable.table.extend.rewriteGetSummaries,
      param,
      sums
    );
  } else {
    return sums;
  }
};

//重写合计方法
const rewriteBoardSalseOutPlan = (url: any, param: any, sums: any) => {
  const { columns, data } = param;
  console.log("重写合计方法", url);

  switch (url) {
    case "/system/salseOutPlan": //销售出货计划合计
      columns.forEach((column: any, index: any) => {
        if (!baTable.table.extend.selection) {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 1) {
            sums[index] = "";
          } else if (index === 2) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        } else {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 1) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        }
      });
      return sums;
    case "/system/buddyStock": //库存数量合计
      columns.forEach((column: any, index: any) => {
        if (!baTable.table.extend.selection) {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 1 || index === 2) {
            sums[index] = "";
          } else if (index === 3) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        } else {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 1) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        }
      });
      return sums;
    case "/system/safeStock": //安全库存量合计
      columns.forEach((column: any, index: any) => {
        if (!baTable.table.extend.selection) {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 1) {
            sums[index] = "";
          } else if (index === 2) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        } else {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 1) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        }
      });
      return sums;
    case "/system/goodsProcessStock": //料品工序库存合计
      columns.forEach((column: any, index: any) => {
        if (!baTable.table.extend.selection) {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 1 || index === 2) {
            sums[index] = "";
          } else if (index === 3) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        } else {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 2) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        }
      });
      return sums;
    case "/system/purchaseStock": //采购入库情况合计
      columns.forEach((column: any, index: any) => {
        if (!baTable.table.extend.selection) {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 1 || index === 2) {
            sums[index] = "";
          } else if (index === 3) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        } else {
          if (index === 0) {
            sums[index] = "合计";
          } else if (index === 2) {
            const values = data.map((item: any) =>
              Number(item[column.property])
            );
            if (!values.every((value: any) => Number.isNaN(value))) {
              sums[index] = `${values.reduce((prev: any, curr: any) => {
                const value = Number(curr);
                if (!Number.isNaN(value)) {
                  return prev + curr;
                } else {
                  return prev;
                }
              }, 0)}`;
            } else {
              sums[index] = "N/A";
            }
          }
        }
      });
      return sums;
    default:
      break;
  }
};
//当用户手动勾选数据行的 Checkbox 时触发的事件
const onSelect = (selection: TableRow[], row: TableRow) => {
  if (
    selection.some((item: TableRow) => {
      return row[baTable.table.pk!] === item[baTable.table.pk!];
    })
  ) {
    if (row.children) {
      selectChildren(row.children, true);
    }
  } else {
    if (row.children) {
      selectChildren(row.children, false);
    }
  }
};

//当选择项发生变化时会触发该事件
const onSelectionChange = (selection: TableRow[]) => {
  emits("action", "selection-change", selection);
};

//当表格的排序条件发生变化的时候会触发该事件 { column, prop, order }
const onSortChange = ({ order, prop }: { order: string; prop: string }) => {
  //历史数据接口
  if (baTable.api.controllerUrl === "/system/electricEnvpub") {
    realTime.orderByColumn = prop;
    realTime.isAsc = order ? (order == "ascending" ? "asc" : "desc") : "";
    console.log(
      "当表格的排序条件发生变化的时候会触发该事件",
      realTime.orderByColumn,
      realTime.isAsc
    );
  }
  emits("action", "sort-change", {
    prop: prop,
    order: order ? (order == "ascending" ? "asc" : "desc") : "",
  });
};

// 每页个数记忆功能
const tableSizeChangeStore = (value: any, path: string) => {
  if ((navTabs as any).pageSizeMap) {
    (navTabs as any).pageSizeMap.set(path + baTable.api.controllerUrl, value);
  } else {
    const m = new Map();
    m.set(path + baTable.api.controllerUrl, value);
    (navTabs as any).pageSizeMap = m;
  }
  console.log("每页个数记忆功能", (navTabs as any).pageSizeMap);
};

//page-size 改变时触发 每页条数
const onTableSizeChange = (val: number) => {
  console.log("baTable", baTable, baTable.api);
  tableSizeChangeStore(val, route.path); // 每页个数记忆功能
  if (
    (route.path === "/admin/EquipM/Monitordetail" &&
      baTable.api.controllerUrl !== "/system/alarm") ||
    (route.path === "/admin/BusinessM/ledgerDetail" &&
      baTable.api.controllerUrl !== "/system/waste") ||
    (route.path === "/admin/system/standard" &&
      baTable.api.controllerUrl !== "/system/group")
  ) {
    proxy.eventBus.emit("pagesize", {
      pageSize: val,
    });
  } else {
    emits("action", "page-size-change", {
      pageSize: val,
    });
  }
};

//current-page 改变时触发 新的当前页
const onTableCurrentChange = (val: number) => {
  if (
    (route.path === "/admin/EquipM/Monitordetail" &&
      baTable.api.controllerUrl !== "/system/alarm") ||
    (route.path === "/admin/BusinessM/ledgerDetail" &&
      baTable.api.controllerUrl !== "/system/waste") ||
    (route.path === "/admin/system/standard" &&
      baTable.api.controllerUrl !== "/system/group")
  ) {
    proxy.eventBus.emit("pageNum", {
      pageNum: val,
    });
  } else {
    emits("action", "current-page-change", {
      pageNum: val,
    });
  }
};

/*
 * 设置折叠所有-递归
 toggleRowExpansion(row, expanded)	用于可扩展的表格或树表格，如果某行被扩展，则切换
  使用第二个参数，您可以直接设置该行应该被扩展或折叠。
 */
const setUnFoldAll = (children: TableRow[], unfold: boolean) => {
  for (const key in children) {
    tableRef.value?.toggleRowExpansion(children[key], unfold);
    if (children[key].children) {
      setUnFoldAll(children[key].children!, unfold);
    }
  }
};

/*
 * 折叠所有
 */
const unFoldAll = (unfold: boolean) => {
  setUnFoldAll(baTable.table.data!, unfold);
};

const getRef = () => {
  return tableRef.value;
};

//当某一行被双击时会触发该事件
const onDbClick = (row: any) => {
  console.log("shuangjilema ");

  proxy.eventBus.emit("toMonitor", row);
};
proxy.eventBus.on("pointer", () => {
  isPointer.value = true;
});
//双击功能的区分
const pointer = ({ row, rowIndex }: any) => {
  return isPointer.value ? "cursor: pointer" : "";
};
onBeforeUnmount(() => {
  proxy.eventBus.off("pointer");
});

provide("route", route);
//子组件暴露给父组件内部属性和方法
defineExpose({
  unFoldAll,
  getRef,
});
</script>
<style lang="scss">
.ba-data-table :deep(.el-button + .el-button) {
  margin-left: 6px;
}

.ba-data-table :deep(.table-header-cell) .cell {
  color: var(--el-text-color-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.table-pagination {
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  background-color: var(--ba-bg-color-overlay);
  padding: 13px 15px;
}
</style>
